﻿using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Reactive.Concurrency;
using System.Reactive.Subjects;

namespace System.Reactive.Linq
{
	public static partial class Observable
	{
		public static IObservable<TResult> ManySelect<TSource, TResult>(this IObservable<TSource> source, Func<IObservable<TSource>, TResult> selector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(selector != null, null, "selector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> ManySelect<TSource, TResult>(this IObservable<TSource> source, Func<IObservable<TSource>, TResult> selector, IScheduler scheduler)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(selector != null, null, "selector != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<Notification<TSource>> Materialize<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<Notification<TSource>>>() != null, null, "Contract.Result<IObservable<Notification<TSource>>>() != null");
			return null;
		}

		public static IObservable<decimal?> Max(this IObservable<decimal?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<decimal?>>() != null, null, "Contract.Result<IObservable<decimal?>>() != null");
			return null;
		}

		public static IObservable<decimal> Max(this IObservable<decimal> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<decimal>>() != null, null, "Contract.Result<IObservable<decimal>>() != null");
			return null;
		}

		public static IObservable<double?> Max(this IObservable<double?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<double?>>() != null, null, "Contract.Result<IObservable<double?>>() != null");
			return null;
		}

		public static IObservable<double> Max(this IObservable<double> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<double>>() != null, null, "Contract.Result<IObservable<double>>() != null");
			return null;
		}

		public static IObservable<float?> Max(this IObservable<float?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<float?>>() != null, null, "Contract.Result<IObservable<float?>>() != null");
			return null;
		}

		public static IObservable<float> Max(this IObservable<float> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<float>>() != null, null, "Contract.Result<IObservable<float>>() != null");
			return null;
		}

		public static IObservable<int?> Max(this IObservable<int?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<int?>>() != null, null, "Contract.Result<IObservable<int?>>() != null");
			return null;
		}

		public static IObservable<int> Max(this IObservable<int> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<int>>() != null, null, "Contract.Result<IObservable<int>>() != null");
			return null;
		}

		public static IObservable<long?> Max(this IObservable<long?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<long?>>() != null, null, "Contract.Result<IObservable<long?>>() != null");
			return null;
		}

		public static IObservable<long> Max(this IObservable<long> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<long>>() != null, null, "Contract.Result<IObservable<long>>() != null");
			return null;
		}

		public static IObservable<TSource> Max<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Max<TSource>(this IObservable<TSource> source, IComparer<TSource> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<IList<TSource>> MaxBy<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Ensures(Contract.Result<IObservable<IList<TSource>>>() != null, null, "Contract.Result<IObservable<IList<TSource>>>() != null");
			return null;
		}

		public static IObservable<IList<TSource>> MaxBy<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IObservable<IList<TSource>>>() != null, null, "Contract.Result<IObservable<IList<TSource>>>() != null");
			return null;
		}

		public static IObservable<TSource> Merge<TSource>(params IObservable<TSource>[] sources)
		{
			Contract.Requires(sources != null, null, "sources != null");
			//Contract.Requires(Contract.ForAll(sources, observable => observable != null), null, "Contract.ForAll(sources, observable => observable != null)");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources)
		{
			Contract.Requires(sources != null, null, "sources != null");
			//Contract.Requires(Contract.ForAll(sources, observable => observable != null), null, "Contract.ForAll(sources, observable => observable != null)");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Merge<TSource>(this IObservable<IObservable<TSource>> sources)
		{
			Contract.Requires(sources != null, null, "sources != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Merge<TSource>(IScheduler scheduler, params IObservable<TSource>[] sources)
		{
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Requires(sources != null, null, "sources != null");
			//Contract.Requires(Contract.ForAll(sources, observable => observable != null), null, "Contract.ForAll(sources, observable => observable != null)");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources, int maxConcurrent)
		{
			Contract.Requires(sources != null, null, "sources != null");
			//Contract.Requires(Contract.ForAll(sources, observable => observable != null), null, "Contract.ForAll(sources, observable => observable != null)");
			Contract.Requires(maxConcurrent > 0, null, "maxConcurrent > 0");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources, IScheduler scheduler)
		{
			Contract.Requires(sources != null, null, "sources != null");
			//Contract.Requires(Contract.ForAll(sources, observable => observable != null), null, "Contract.ForAll(sources, observable => observable != null)");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Merge<TSource>(this IObservable<IObservable<TSource>> sources, int maxConcurrent)
		{
			Contract.Requires(sources != null, null, "sources != null");
			Contract.Requires(maxConcurrent > 0, null, "maxConcurrent > 0");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Merge<TSource>(this IObservable<TSource> first, IObservable<TSource> second)
		{
			Contract.Requires(first != null, null, "first != null");
			Contract.Requires(second != null, null, "second != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources, int maxConcurrent, IScheduler scheduler)
		{
			Contract.Requires(sources != null, null, "sources != null");
			//Contract.Requires(Contract.ForAll(sources, observable => observable != null), null, "Contract.ForAll(sources, observable => observable != null)");
			Contract.Requires(maxConcurrent > 0, null, "maxConcurrent > 0");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Merge<TSource>(this IObservable<TSource> first, IObservable<TSource> second, IScheduler scheduler)
		{
			Contract.Requires(first != null, null, "first != null");
			Contract.Requires(second != null, null, "second != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<decimal?> Min(this IObservable<decimal?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<decimal?>>() != null, null, "Contract.Result<IObservable<decimal?>>() != null");
			return null;
		}

		public static IObservable<decimal> Min(this IObservable<decimal> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<decimal>>() != null, null, "Contract.Result<IObservable<decimal>>() != null");
			return null;
		}

		public static IObservable<double?> Min(this IObservable<double?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<double?>>() != null, null, "Contract.Result<IObservable<double?>>() != null");
			return null;
		}

		public static IObservable<double> Min(this IObservable<double> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<double>>() != null, null, "Contract.Result<IObservable<double>>() != null");
			return null;
		}

		public static IObservable<float?> Min(this IObservable<float?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<float?>>() != null, null, "Contract.Result<IObservable<float?>>() != null");
			return null;
		}

		public static IObservable<float> Min(this IObservable<float> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<float>>() != null, null, "Contract.Result<IObservable<float>>() != null");
			return null;
		}

		public static IObservable<int?> Min(this IObservable<int?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<int?>>() != null, null, "Contract.Result<IObservable<int?>>() != null");
			return null;
		}

		public static IObservable<int> Min(this IObservable<int> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<int>>() != null, null, "Contract.Result<IObservable<int>>() != null");
			return null;
		}

		public static IObservable<long?> Min(this IObservable<long?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<long?>>() != null, null, "Contract.Result<IObservable<long?>>() != null");
			return null;
		}

		public static IObservable<long> Min(this IObservable<long> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<long>>() != null, null, "Contract.Result<IObservable<long>>() != null");
			return null;
		}

		public static IObservable<TSource> Min<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Min<TSource>(this IObservable<TSource> source, IComparer<TSource> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<IList<TSource>> MinBy<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Ensures(Contract.Result<IObservable<IList<TSource>>>() != null, null, "Contract.Result<IObservable<IList<TSource>>>() != null");
			return null;
		}

		public static IObservable<IList<TSource>> MinBy<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IObservable<IList<TSource>>>() != null, null, "Contract.Result<IObservable<IList<TSource>>>() != null");
			return null;
		}

		public static IEnumerable<TSource> MostRecent<TSource>(this IObservable<TSource> source, TSource initialValue)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IEnumerable<TSource>>() != null, null, "Contract.Result<IEnumerable<TSource>>() != null");
			return null;
		}

		public static IConnectableObservable<TResult> Multicast<TSource, TResult>(this IObservable<TSource> source, ISubject<TSource, TResult> subject)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(subject != null, null, "subject != null");
			Contract.Ensures(Contract.Result<IConnectableObservable<TResult>>() != null, null, "Contract.Result<IConnectableObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> Multicast<TSource, TIntermediate, TResult>(this IObservable<TSource> source, Func<ISubject<TSource, TIntermediate>> subjectSelector, Func<IObservable<TIntermediate>, IObservable<TResult>> selector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(subjectSelector != null, null, "subjectSelector != null");
			Contract.Requires(selector != null, null, "selector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}
	}
}